﻿#include "OriginPCH.h"
#include "Application.h"
#include "Input.h"
#include "Log.h"
#include "Renderer/RenderCommand.h"
#include "Renderer/Renderer.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>

namespace Origin
{
#define BIND_EVENT_FN(x) std::bind(&Application::##x, this, std::placeholders::_1)

    Application* Application::_instance = nullptr;

    Application::Application()
    {
        _window = std::unique_ptr<Window>(Window::Create());
        _window->SetEventCallback(BIND_EVENT_FN(OnEvent));
        _instance = this;
        Renderer::Init();
        _imGuiLayer = new ImGuiLayer();
        PushOverlay(_imGuiLayer);
    }

    void Application::PushLayer(Layer* layer)
    {
        _layerStack.PushLayer(layer);
    }

    void Application::PushOverlay(Layer* layer)
    {
        _layerStack.PushOverlay(layer);
    }

    void Application::OnEvent(Event& e)
    {
        // 临时写一个关闭窗口的功能
        EventDispatcher dispatcher(e);
        // Dispatch传入的是一个返回类型为bool，参数为T&的方法
        dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose));

        for (auto it = _layerStack.end(); it > _layerStack.begin(); )
        {
            --it;
            (*it)->OnEvent(e);
        }
    }

    bool Application::OnWindowClose(WindowCloseEvent& e)
    {
        _running = false;
        return true;
    }

    void Application::Run()
    {
        WindowResizeEvent e(1280, 720);

        while (_running)
        {
            float time = (float)glfwGetTime();
            Timestep timestep = time - _lastFrameTime;
            _lastFrameTime = time;

            for (auto layer : _layerStack)
                layer->OnUpdate(timestep);

            _imGuiLayer->Begin();
            for (auto layer: _layerStack)
                layer->OnImGuiRender();
            _imGuiLayer->End();

            // GLFW swap frame buffer
            _window->OnUpdate();
        }
    }
}